{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2bd760c2-74dd-4b75-b77f-adeb04788d96",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 安装必要的依赖（如果尚未安装）\n",
    "# !pip install matplotlib numpy torch\n",
    "\n",
    "# 导入必要的库\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# 设置中文字体支持 - 解决警告问题\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体作为中文字体\n",
    "plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题\n",
    "\n",
    "# 设置随机种子以确保结果可重现\n",
    "torch.manual_seed(42)\n",
    "np.random.seed(42)\n",
    "\n",
    "# 1. 生成合成数据函数\n",
    "def generate_data(num_samples=100, true_w=2.0, true_b=1.0, noise_std=0.1):\n",
    "    \"\"\"\n",
    "    生成线性回归数据\n",
    "    参数:\n",
    "        num_samples: 样本数量\n",
    "        true_w: 真实的权重值\n",
    "        true_b: 真实的偏置值\n",
    "        noise_std: 噪声标准差\n",
    "    返回:\n",
    "        X: 输入特征\n",
    "        y: 目标值\n",
    "    \"\"\"\n",
    "    # 生成均匀分布的x值，范围从-1到1\n",
    "    X = torch.linspace(-1, 1, num_samples).reshape(-1, 1)\n",
    "    # 计算y值: y = w*x + b + 噪声（正态分布）\n",
    "    y = true_w * X + true_b + torch.normal(0, noise_std, (num_samples, 1))\n",
    "    \n",
    "    return X, y\n",
    "\n",
    "# 设置真实参数\n",
    "TRUE_W = 3.5    # 真实的权重\n",
    "TRUE_B = 2.0    # 真实的偏置\n",
    "NUM_SAMPLES = 200  # 样本数量\n",
    "\n",
    "# 生成数据\n",
    "X, y = generate_data(NUM_SAMPLES, TRUE_W, TRUE_B)\n",
    "\n",
    "# 2. 可视化生成的数据\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.scatter(X.numpy(), y.numpy(), alpha=0.7, label='生成数据')\n",
    "plt.plot(X.numpy(), (TRUE_W * X + TRUE_B).numpy(), 'r-', linewidth=2, label='真实直线')\n",
    "plt.xlabel('X')\n",
    "plt.ylabel('y')\n",
    "plt.title('生成的线性回归数据')\n",
    "plt.legend()\n",
    "plt.grid(True)\n",
    "plt.show()\n",
    "\n",
    "# 3. 定义线性回归模型\n",
    "class LinearRegressionModel(nn.Module):\n",
    "    \"\"\"\n",
    "    简单的线性回归模型\n",
    "    形式: y = w*x + b\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        super(LinearRegressionModel, self).__init__()\n",
    "        # 定义一个线性层，输入和输出都是1维\n",
    "        self.linear = nn.Linear(1, 1)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        # 前向传播：计算预测值\n",
    "        return self.linear(x)\n",
    "\n",
    "# 4. 初始化模型、损失函数和优化器\n",
    "model = LinearRegressionModel()           # 创建模型实例\n",
    "criterion = nn.MSELoss()                  # 使用均方误差作为损失函数\n",
    "optimizer = optim.SGD(model.parameters(), lr=0.1)  # 使用随机梯度下降优化器\n",
    "\n",
    "# 5. 训练模型\n",
    "num_epochs = 100      # 训练轮数\n",
    "losses = []           # 记录每个epoch的损失\n",
    "learned_weights = []  # 记录学习到的权重\n",
    "learned_biases = []   # 记录学习到的偏置\n",
    "\n",
    "print(\"开始训练...\")\n",
    "for epoch in range(num_epochs):\n",
    "    # 前向传播：计算预测值\n",
    "    predictions = model(X)\n",
    "    # 计算损失：预测值与真实值之间的差异\n",
    "    loss = criterion(predictions, y)\n",
    "    \n",
    "    # 反向传播和优化\n",
    "    optimizer.zero_grad()  # 清零梯度，防止梯度累积\n",
    "    loss.backward()        # 反向传播，计算梯度\n",
    "    optimizer.step()       # 更新模型参数\n",
    "    \n",
    "    # 记录训练信息\n",
    "    losses.append(loss.item())\n",
    "    learned_weights.append(model.linear.weight.item())\n",
    "    learned_biases.append(model.linear.bias.item())\n",
    "    \n",
    "    # 每10个epoch打印一次进度\n",
    "    if (epoch + 1) % 10 == 0:\n",
    "        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.6f}')\n",
    "\n",
    "print(\"训练完成!\")\n",
    "\n",
    "# 6. 可视化训练过程\n",
    "plt.figure(figsize=(12, 4))\n",
    "\n",
    "# 绘制损失曲线\n",
    "plt.subplot(1, 2, 1)\n",
    "plt.plot(losses)\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('训练损失曲线')\n",
    "plt.grid(True)\n",
    "\n",
    "# 绘制参数收敛情况\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(learned_weights, label='学习到的权重')\n",
    "plt.axhline(y=TRUE_W, color='r', linestyle='--', label='真实权重')\n",
    "plt.plot(learned_biases, label='学习到的偏置')\n",
    "plt.axhline(y=TRUE_B, color='g', linestyle='--', label='真实偏置')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('参数值')\n",
    "plt.title('参数收敛情况')\n",
    "plt.legend()\n",
    "plt.grid(True)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# 7. 最终结果评估\n",
    "final_w = model.linear.weight.item()  # 获取最终学习到的权重\n",
    "final_b = model.linear.bias.item()    # 获取最终学习到的偏置\n",
    "\n",
    "print(\"\\n=== 最终结果 ===\")\n",
    "print(f\"真实参数: w = {TRUE_W:.4f}, b = {TRUE_B:.4f}\")\n",
    "print(f\"学习参数: w = {final_w:.4f}, b = {final_b:.4f}\")\n",
    "print(f\"权重误差: {abs(final_w - TRUE_W):.6f}\")\n",
    "print(f\"偏置误差: {abs(final_b - TRUE_B):.6f}\")\n",
    "\n",
    "# 8. 可视化拟合结果\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.scatter(X.numpy(), y.numpy(), alpha=0.7, label='生成数据')\n",
    "plt.plot(X.numpy(), (TRUE_W * X + TRUE_B).numpy(), 'r-', linewidth=2, label='真实直线')\n",
    "plt.plot(X.numpy(), predictions.detach().numpy(), 'g--', linewidth=2, label='拟合直线')\n",
    "plt.xlabel('X')\n",
    "plt.ylabel('y')\n",
    "plt.title('线性回归拟合结果')\n",
    "plt.legend()\n",
    "plt.grid(True)\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
